package com.casic.ccp.flying.youth.timeseriesdata.config;

import com.casic.ccp.flying.youth.timeseriesdata.model.SqlPreparation;
import com.casic.ccp.flying.youth.timeseriesdata.sql.SqlPreparationFactory;
import com.casic.ccp.flying.youth.timeseriesdata.sql.SqlPreparationPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PreDestroy;
import java.time.Duration;

/**
 * sql 准备工作配置
 *
 * @Author: 贺坤
 * @Date: 2021/9/18 15:08
 */
@Configuration
public class SqlPreparationConfig {


    private SqlPreparationPool pool;
    /**
     * 最大空闲
     */
    @Value("${time-series-data.pool.maxIdle}")
    private Integer maxIdle = 100;
    /**
     * 最大总数
     */
    @Value("${time-series-data.pool.maxTotal}")
    private Integer maxTotal = 1000;
    /**
     * 最小空闲
     */
    @Value("${time-series-data.pool.minIdle}")
    private Integer minIdle = 50;
    /**
     * 初始化数
     */
    @Value("${time-series-data.pool.initialSize}")
    private Integer initialSize = 100;
    /**
     * 时候开启对象池
     */
    @Value("${time-series-data.pool.switch}")
    private Boolean switchPool = true;

    @Bean
    protected SqlPreparationPool sqlPreparationPool(SqlPreparationFactory sqlPreparationFactory) {
        //设置对象池的相关参数
        GenericObjectPoolConfig<SqlPreparation> poolConfig = new GenericObjectPoolConfig<>();
        poolConfig.setMaxIdle(maxIdle);
        poolConfig.setMaxTotal(maxTotal);
        poolConfig.setMinIdle(minIdle);
        poolConfig.setBlockWhenExhausted(true);
        poolConfig.setTestOnBorrow(true);
        poolConfig.setTestOnReturn(true);
        poolConfig.setTestWhileIdle(true);
        poolConfig.setTimeBetweenEvictionRuns(Duration.ofMillis(1000 * 60 * 30));
        //一定要关闭jmx，不然springboot启动会报已经注册了某个jmx的错误
        poolConfig.setJmxEnabled(false);
        //新建一个对象池,传入对象工厂和配置
        pool = new SqlPreparationPool(switchPool,sqlPreparationFactory, poolConfig);
        initPool(initialSize, maxIdle);
        return pool;
    }

    /**
     * 预先加载testObject对象到对象池中
     *
     * @param initialSize 初始化连接数
     * @param maxIdle     最大空闲连接数
     */
    private void initPool(int initialSize, int maxIdle) {
        if (initialSize <= 0) {
            return;
        }

        int size = Math.min(initialSize, maxIdle);
        for (int i = 0; i < size; i++) {
            try {
                pool.addObject();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 结束的时候销毁对象池
     */
    @PreDestroy
    public void destroy() {
        if (pool != null) {
            pool.close();
        }
    }
}
